home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pctchnqs / 1991 / number2 / hpfont.cpp < prev    next >
C/C++ Source or Header  |  1991-03-08  |  8KB  |  278 lines

  1. //-------------------------------------------------------------//
  2. // File:   HpFont.Cpp                                          //
  3. // Desc:   Font implementation for HP Soft Font                //
  4. // Author: Marv Luse, Autumn Hill Software                     //
  5. //-------------------------------------------------------------//
  6.  
  7. #include "stdlib.h"
  8. #include "stdio.h"
  9. #include "ctype.h"
  10. #include "HpFont.Hpp"
  11.  
  12. #define BUF_SIZ 128
  13.  
  14. static int cur_ch = 0;
  15. static int hp_stat;
  16.  
  17. //............................... Skip next n bytes from a file
  18.  
  19. static int skip_inp( FILE *inp, int nbytes )
  20. {
  21.      int  n;
  22.      char buf[BUF_SIZ];
  23.  
  24.      while( nbytes > 0 )
  25.      {
  26.         n = nbytes > BUF_SIZ ? BUF_SIZ : nbytes;
  27.         if( fread(buf, n, 1, inp) != 1 )
  28.            return 0;
  29.         nbytes -= n;
  30.      }
  31.      return 1;
  32. }
  33.  
  34. //......................... Determine char range from font type
  35.  
  36. static void char_range( int font_type, int& min_ch, int& max_ch )
  37. {
  38.      switch( font_type )
  39.      {
  40.           case 0 : // 7-bit, 32-127
  41.                    min_ch = 32;
  42.                    max_ch = 127;
  43.                    break;
  44.  
  45.           case 1 : // 8-bit, 32-127 and 160-255
  46.                    min_ch = 32;
  47.                    max_ch = 255;
  48.                    break;
  49.  
  50.           default: // 8-bit, everything
  51.                    min_ch = 0;
  52.                    max_ch = 255;
  53.                    break;
  54.      }
  55. }
  56.  
  57. //................. Determine esq type and its numeric argument
  58.  
  59. static void get_esq_values( char esq_buf[], int& type, int& parm )
  60. {
  61.      int i;
  62.      char  c1, c2, clast;
  63.  
  64.      /* extract group char and terminating char */
  65.      c1 = esq_buf[1];
  66.      c2 = esq_buf[2];
  67.      i = 0;
  68.      while( esq_buf[i] ) i++;
  69.      clast = esq_buf[i-1];
  70.  
  71.      /* determine type */
  72.      if( (c1==')') && (c2=='s') && (clast=='W') )
  73.         type = eFONTDESC;
  74.      else if( (c1=='(') && (c2=='s') && (clast=='W') )
  75.         type = eCHARDESC;
  76.      else if( (c1=='*') && (c2=='c') && (clast=='E') )
  77.         type = eCHARCODE;
  78.      else
  79.         type = eUNKNOWN;
  80.  
  81.      /* get the sequence's value field */
  82.      parm = 0;
  83.      i    = 0;
  84.      while( (esq_buf[i]) && (! isdigit(esq_buf[i])) ) i++;
  85.      if( isdigit(esq_buf[i]) )
  86.         parm = atoi( esq_buf+i );
  87. }
  88.  
  89.  
  90. //.................... Read the next esc seq from the font file
  91.  
  92. static int get_esq( FILE *inp, char esq_buf[], int buf_len )
  93. {
  94.      int i, nbytes;
  95.  
  96.      nbytes = 0;
  97.  
  98.      while( (i=fgetc( inp )) != EOF )
  99.      {
  100.        if( nbytes == buf_len )
  101.        {
  102.           hp_stat = hpOVRFLOW;
  103.           return 0;
  104.        }
  105.        esq_buf[nbytes++] = (char) i;
  106.        // check for end of sequence
  107.        if( isupper( i ) ) break;
  108.      }
  109.  
  110.      // validity check - first char should be decimal 27
  111.      if( (nbytes > 0) && (esq_buf[0] != 27) )
  112.      {
  113.         hp_stat = hpBADFMT;
  114.         return 0;
  115.      }
  116.  
  117.      // add a terminating null
  118.      esq_buf[nbytes] = 0;
  119.  
  120.      return( nbytes );
  121. }
  122.  
  123. //.................................... set font-related metrics
  124.  
  125. void HpFont::SetFontMetrics( font_desc& fd )
  126. {
  127.      cell_w  = REV_WRD( fd.cell_width );
  128.      cell_h  = REV_WRD( fd.cell_height );
  129.      ascent  = REV_WRD( fd.bl_dist );
  130.      descent = cell_h - ascent;
  131.      pitch   = REV_WRD( fd.pitch ) >> 2;
  132. }
  133.  
  134. //.................................... set char-related metrics
  135.  
  136. void HpFont::SetCharMetrics( Character& c, char_desc& cd )
  137. {
  138.      c.left_ofs = REV_WRD( cd.left_ofs );
  139.      c.top_ofs  = REV_WRD( cd.top_ofs );
  140.      c.width    = REV_WRD( cd.char_width );
  141.      c.height   = REV_WRD( cd.char_height );
  142.      c.rowbytes = (c.width + 7) / 8;
  143.      c.delta_x  = (REV_WRD( cd.delta_x ) + 3) >> 2;
  144. }
  145.  
  146. //........................ default destructor
  147.  
  148. HpFont::~HpFont( )
  149. {
  150. }
  151.  
  152. //........................ instantiate a font from HP Soft Font
  153.  
  154. HpFont::HpFont( char *path ) : Font( )
  155. {
  156.      FILE      *inp;
  157.      char       esq_buf[BUF_SIZ];
  158.      font_desc  fd;
  159.      char_desc  cd;
  160.      int        n, esq_type, esq_parm;
  161.  
  162.      // open file
  163.      if( (inp = fopen( path, "rb" )) == NULL )
  164.      {
  165.         hpstatus = hpNOTFOUND;
  166.         fstatus  = fntFAILED;
  167.         return;
  168.      }
  169.  
  170.      // initialize static globals
  171.      cur_ch = 0;
  172.      hp_stat = hpNOINIT;
  173.  
  174.      // scan the file and process
  175.      while( (get_esq( inp, esq_buf, BUF_SIZ ) > 0) &&
  176.             (hp_stat == hpNOINIT) )
  177.      {
  178.  
  179.         // get the escape sequence type and its
  180.         // numeric value field...
  181.         get_esq_values( esq_buf, esq_type, esq_parm );
  182.  
  183.         // process the sequence.....
  184.         switch( esq_type )
  185.         {
  186.  
  187.           case eFONTDESC:  //............... font descriptor
  188.                // read the descriptor
  189.                if( fread( &fd, sizeof(font_desc), 1, inp ) != 1 )
  190.                {
  191.                     hp_stat = hpIOERROR;
  192.                     break;
  193.                }
  194.                // allocate the Character array, init font stuff
  195.                char_range( (int) fd.font_type, min_ch, max_ch );
  196.                ch_cnt = max_ch - min_ch + 1;
  197.                ch = new Character[ch_cnt];
  198.                if( ch == 0 )
  199.                {
  200.                     hp_stat = hpNOMEM;
  201.                     break;
  202.                }
  203.                SetFontMetrics( fd );
  204.                // skip any trailing info
  205.                if( esq_parm > sizeof(font_desc) )
  206.                     skip_inp( inp, esq_parm-sizeof(font_desc) );
  207.                break;
  208.  
  209.           case eCHARDESC:  //............... char descriptor
  210.                // read the descriptor
  211.                if( fread( &cd, sizeof(char_desc), 1, inp ) != 1 )
  212.                {
  213.                     hp_stat = hpIOERROR;
  214.                     break;
  215.                }
  216.                // is this a char we discard?
  217.                if( (cur_ch < min_ch) || (cur_ch > max_ch) )
  218.                {
  219.                     skip_inp( inp, esq_parm-sizeof(char_desc) );
  220.                     break;
  221.                }
  222.                // set char table entry
  223.                Character *c = &ch[cur_ch-min_ch];
  224.                SetCharMetrics( *c, cd );
  225.                // allocate this char's bitmap
  226.                int i = c->rowbytes * c->height;
  227.                if( i )
  228.                {
  229.                   c->mask = new char[i];
  230.                   if( c->mask == 0 )
  231.                   {
  232.                      hp_stat = hpNOMEM;
  233.                      break;
  234.                   }
  235.                }
  236.                else
  237.                   c->mask = 0;
  238.                // get the bitmap which follows
  239.                if( esq_parm > sizeof(char_desc) )
  240.                {
  241.                   n = esq_parm - sizeof(char_desc);
  242.                   if( fread( c->mask, n, 1, inp ) != 1 )
  243.                   {
  244.                      hp_stat = hpIOERROR;
  245.                      break;
  246.                   }
  247.                }
  248.                break;
  249.  
  250.           case eCHARCODE:  //........ specify character code
  251.                // save char code for later use
  252.                cur_ch = esq_parm;
  253.                break;
  254.  
  255.           case eUNKNOWN:  //........ unknown seq - ignore it
  256.                break;
  257.         }
  258.  
  259.      }
  260.  
  261.      fclose( inp );
  262.  
  263.      // update Font and HpFont status members
  264.      if( hp_stat != hpNOINIT )
  265.      {
  266.         hpstatus = hp_stat;
  267.         fstatus  = fntFAILED;
  268.         return;
  269.      }
  270.      hpstatus = hpOKAY;
  271.      fstatus  = fntOKAY;
  272.  
  273.      // set width of blank-- may not have been a definition
  274.      Character *b = &ch[32-min_ch];
  275.      if( b->delta_x == 0 )
  276.         b->delta_x = pitch;
  277. }
  278.